package p.ithorns.integration.hazelcast.mqtt;

import com.hazelcast.cluster.Endpoint;
import com.hazelcast.core.HazelcastInstance;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import p.ithorns.framework.common.utils.ByteUtil;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @Author: liuhaitao
 * @Date: 2022/8/18 17:42
 * @Description: 定位数据处理
 */
@Slf4j
//@Service
public class MqttLocateRawHandler extends AbstractDataHandler<Payload> {


    private final Endpoint endpoint;

    public MqttLocateRawHandler(HazelcastInstance hz) {
        this.endpoint = hz.getLocalEndpoint();
    }

    @Override
    public Serializable getCode() {
        return UpMsgType.LOCATE;
    }

    @Override
    public void handle(Payload frame) {

        byte[] bytes = frame.getRaw();
        ByteBuf buffer = DataHandlerContext.getAllocator().buffer(bytes.length);
        buffer.writeBytes(bytes);

        CardRaw.CardRawBuilder builder = CardRaw.builder();

        // 指令
        int code = buffer.readByte();
        setCardStatus(builder, code);

        // 电量
        byte batBit = buffer.readByte();
        double battery = Byte.toUnsignedInt(batBit) * 20D / 1000D;

        // 计步  标签卡1s内步数，0xff为无效值
        int step = buffer.readByte();

        List<BeaconRaw> beaconRaws = resolveBeacons(buffer);

        // 释放byte缓冲区
        ReferenceCountUtil.release(buffer);

        CardRaw cardRaw = builder
                .cardCode(frame.getDevId())
                .voltage(battery)
                .step(step)
                .timestamp(frame.getTimestamp())
                .beaconRaws(beaconRaws)
                .build();

        // 分发到解算链
        log.info("节点：[{}] =========> {}", endpoint.getSocketAddress(), cardRaw);
    }

    /**
     * 解析信标
     * 信标数据：信标编号(3位) + RSSI(1位) + 电量(1位)
     */
    private List<BeaconRaw> resolveBeacons(ByteBuf buffer) {
        int retain = buffer.readableBytes();
        int beaconCnt = retain / 5;
        return IntStream.range(0, beaconCnt)
                .mapToObj(i -> toBeaconRaw(buffer))
                .collect(Collectors.toList());
    }

    /**
     * 转信标数据对象
     */
    private BeaconRaw toBeaconRaw(ByteBuf beaconBuf) {
        // BeaconId
        byte[] deviceIdBytes = new byte[3];
        beaconBuf.readBytes(deviceIdBytes);
        String beaconId = ByteUtil.bytes2HexStr(deviceIdBytes);

        // rssi
        int rssi = beaconBuf.readByte();

        // 电量
        double battery = Byte.toUnsignedInt(beaconBuf.readByte()) * 20D / 1000D;

        // 构建Msg
        return BeaconRaw.builder()
                .beaconCode(beaconId)
                .rssi(rssi)
                .volt(battery)
                .build();
    }

    private void setCardStatus(CardRaw.CardRawBuilder builder, int code) {
        LocateType type = LocateType.of(code);
        if (null != type) {
            switch (type) {
                case SOS:
                    builder.sos(true).sleep(false);
                    break;
                case DEV_SLEEP:
                    builder.sleep(true).sos(false);
                    break;
                case DEV_WAKE_UP:
                    builder.sleep(false).sos(false);
                    break;
                default:

            }
        }
    }

}